﻿using System.Threading.Channels;

namespace Lesson12_委托;
//用来存储对应格式的函数
#region 知识点三 定义自定义委托
//一般不写访问修饰符 默认为public 在其他命名空间也能使用 
//若访问修饰符为 Private 则在别的命名空间无法使用
//一般为public
public delegate void MyFun();   //定义一个无参无返回值的函数容器

delegate int MyFun1 (int a);   //函数名不能重复（不涉及到方法的重载）
#endregion

#region 知识点四 委托的使用
//委托变量是函数的容器 

//委托常用在
//作为类的成员变量
//作为函数的参数
class Test
{
    public MyFun fun;
    public MyFun1 fun1;


    public void TestFun(MyFun fun, MyFun1 fun1)
    {
        //可以实现逻辑的延时
        int i = 1;
        i *= 2;

        fun();
       fun1(1);
    }
    #endregion

    #region 知识点五 委托变量可以存储多个函数

    #region 增
    #endregion
    public void AddTest(MyFun fun, MyFun1 fun1)  //它通过“+=”操作符将传入的委托添加到类的成员fun和fun1上。这实际上是在说：“当调用Test类实例的fun或fun1时，不仅会执行之前已添加的所有方法，还会执行这次传入的方法”。
    {
    this.fun += fun;
    this.fun1 += fun1;
    }
    #endregion
}
class Program
{
    static void Main(string[] args)
    {
        #region 知识点一 委托是什么
        //委托是函数（方法）的变量类型
        //用来存储，传递函数（方法 ）
        //委托本质是一个类 用来定义函数（方法）的类型  （返回值和参数的类型）
        //不同的函数（方法）必须对应和各自“格式”一致的委托 
        #endregion
// 委托的声明


        #region 知识点二 委托的申明
        //关键字 delegate
        //记忆方式 函数声明语法前加 delegate
        // 委托的声明
        //using System;

        #endregion

        #region 知识点三
        //格式要匹配
        MyFun f = new MyFun(Fun);   //用f来装载Fun的方法   
        f.Invoke();

        static void Fun()
        {
            Console.WriteLine("张三做什么");
        }

        static void Fun5()
        {
            Console.WriteLine("李四做什么");
        }
        
        f();

        static int Fun1(int value)
        {
            return value;
        }

        MyFun1 f1 = new MyFun1(Fun1);
        Console.WriteLine(f1.Invoke(1));
        Console.WriteLine("***************");
        MyFun1 f2 = Fun1;
        Console.WriteLine(f2(1));

        #endregion

        #region 知识点四
        Test t = new Test();
        t.TestFun(Fun, Fun1);
        #endregion

        #region 知识点五
        MyFun ff = new MyFun(Fun);
        ff += Fun5;
        Console.WriteLine("************");
        ff();


        Console.WriteLine("***********");
        MyFun d = null;
        d += Fun;
        d += Fun5;
        d();

        // d -= Fun;
        // d -= Fun5;
        // d();
        Console.WriteLine("***************");
        #endregion
          #region  委托变量可以装载多个函数
          
           Test t1 = new Test();
           t1.AddTest(Fun,Fun1);
           t1.fun();
           t1.fun1(50);


           #endregion

           Console.WriteLine("**************************");
           #region 知识点六 使用系统自带委托
           //方便用户进行使用
           //无返回值的委托
           static void Fun9(int i, string s)
           {
               
           }
           //可以传n个参数
           Action<int, string> action2 = Fun9;
           Action action = Fun;
           action();
           //泛型委托
           
           Func<int> a = new Func<int>(Fun6);
           
           static int Fun6()
           {
               return 1;
           }
           //可以传n个参数，且有返回值的 同样系统提供16种
           Func<int, int> action3 = Fun10;

           static int Fun10(int i)
           {
               return 1;
           }
           #endregion


    }
}
//总结
//委托 就是 装载 传递函数的容器而已
//可以使用委托变量来存储函数或者传递函数
//系统提供了很多委托供我们使用
//Action 没有返回值 ，参数提供了 0-16 个委托供我们使用
//Func 有返回 ，参数同样提供了 0-16 个委托供我们使用